use std::ops::Mul;

use axum::Json;
use http::HeaderMap;
use serde_json::{Value,json};

use crate::{chrono, code, encrypt, query, reqwest::ajax, uuid};

pub mod pay_h5;
pub mod pay_jsapi;
pub mod pay_app;


pub const HOST:&str = "https://api.mch.weixin.qq.com";

pub async fn place_order(header:HeaderMap, url:&str, serial_no:&str, param:Value )  -> Result<Value, Json<Value>> {
    let mchid = query::str(&param, "mchid")?;
    let authorization = get_auth("POST", url, &param.to_string(),  &mchid, serial_no).await?;
    if let Some(f) = header.get("User-Agent") {
        let agent = f.to_str().unwrap_or_default();
        let client = reqwest::Client::new();
        
        ajax(client.post(format!("{HOST}{url}"))
        .header("Accept", "application/json")
        .header("Content-Type", "application/json")
        .header("User-Agent", agent)
        .header("Authorization", authorization)
        .json(&param).send().await).await
    }else{
        Err(code::err_("User-Agent 不存在"))
    }
}

// 查询订单
pub async fn search_order(no:&str, mchid:&str, serial_no:&str) -> Result<Json<Value>, Json<Value>>{
    let url = "/v3/pay/transactions/id/";
    let authorization = get_auth("GET", url, "",  &mchid, serial_no).await?;
    let client = reqwest::Client::new();
    let rs = ajax(client.post(format!("{HOST}{url}{no}"))
    .header("Accept", "application/json")
    // .header("Content-Type", "application/json")
    // .header("User-Agent", agent)
    .header("Authorization", authorization).send().await).await.unwrap_or_default();
    Ok(code::data_(rs))
}
// 关闭订单
pub async fn close_order(no:&str, mchid:&str, serial_no:&str) -> Result<Json<Value>, Json<Value>>{
    let url = "/v3/pay/transactions/out-trade-no/";
    let authorization = get_auth("POST", url, no,  &mchid, serial_no).await?;
    let client = reqwest::Client::new();
    let rs = ajax(client.post(format!("{HOST}{url}{no}/close"))
    .header("Accept", "application/json")
    .header("Content-Type", "application/json")
    .header("Authorization", authorization).send().await).await.unwrap_or_default();
    Ok(code::data_(rs))
}
// 获取 Authorization 验证
pub async fn get_auth( method:&str, url:&str, body:&str, mchid:&str, serial_no:&str) -> Result<String, Json<Value>> {
    // 商户号
    // let mchid;
    // 商户 API 证书序列号
    //  let serial_no;
    // 随机字符串
    let nonce_str = uuid::create_simple();
    // 当前时间戳
    let timestamp = chrono::now().to_string();

    // 构造签名串
    let sign = format!("{method}\n{url}\n{timestamp}\n{nonce_str}\n{body}\n");
    // 使用商户私钥对待签名串进行SHA256 with RSA签名，并对签名结果进行Base64编码得到签名值
    let signature = encrypt::rsa::sign_sha256(&sign, "./pem/apiclient_key.pem").await?;
   
    let rs = format!("WECHATPAY2-SHA256-RSA2048 mchid=\"{mchid}\",serial_no=\"{serial_no}\",nonce_str=\"{nonce_str}\",timestamp=\"{timestamp}\",signature=\"{signature}\"");
    Ok(rs)
}

// 将钱转为分
pub fn get_fen(price:&str) -> Result<i64, Json<Value>>{
    let price = price.replace(",", "");
    let price = price.parse::<f32>().unwrap_or_default();
    let price = price.mul(100.0);
    let price = price as i64;
    if price <= 0 {
        Err(code::err_("支付金额必须大于 0"))
    }else {
        Ok(price)
    }
}
// 返回调起支付的参数
pub async fn payment(appid:&str, prepay_id:&str) -> Result<Json<Value>, Json<Value>>{
    // 随机串
    let nonce_str = uuid::create_simple();
    // 当前时间戳
    let timestamp = chrono::now().to_string();
    // package
    let package = format!("prepay_id={prepay_id}");
    // 签名
    let sign = format!("{appid}\n{timestamp}\n{nonce_str}\n{package}\n");
    let signature = encrypt::rsa::sign_sha256(&sign, "./pem/apiclient_key.pem").await?;

    let data = json!({
        "appId": appid,                             //公众号ID，由商户传入     
        "timeStamp": timestamp,                    //时间戳，自1970年以来的秒数     
        "nonceStr": nonce_str,                     //随机串     
        // "prepayId": prepay_id,
        "package": package,
        "signType": "RSA",                         //微信签名方式：     
        "paySign": signature                       //微信签名 
    });
    Ok(code::data_(data))
}